package org.example.day10;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 4.1.5: 使用多个Condition实现通知部分线程 错误用法
 * Question: 多个Condition是怎么实现指定唤醒的?
 * Answer: 同一把锁可以new多个Condition，如conditionA，conditionB，线程A通过conditionA.await()释放锁等待，则使用conditionA.notify()来只唤醒线程A。
 */
public class MyThread10 {
    private Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();
    public void awaitA(){
        try {
            lock.lock();
            System.out.println("ThreadName = " + Thread.currentThread().getName() + " awaitA begin time = " + System.currentTimeMillis());
            condition.await();
            System.out.println("ThreadName = " + Thread.currentThread().getName() + " awaitA end time = " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void awaitB(){
        try {
            lock.lock();
            System.out.println("ThreadName = " + Thread.currentThread().getName() + " awaitB begin time = " + System.currentTimeMillis());
            condition.await();
            System.out.println("ThreadName = " + Thread.currentThread().getName() + " awaitB end time = " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void signalAll(){
        try {
            lock.lock();
            System.out.println("ThreadName = " + Thread.currentThread().getName() + " signalAll time = " + System.currentTimeMillis());
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyThread10 m10 = new MyThread10();
        Thread10A ta = new Thread10A(m10);
        ta.setName("A");
        ta.start();
        Thread10B tb = new Thread10B(m10);
        tb.setName("B");
        tb.start();
        Thread.sleep(3000);
        m10.signalAll();  //全部唤醒
    }
}

class Thread10A extends Thread{
    private MyThread10 m10;

    public Thread10A(MyThread10 m10) {
        this.m10 = m10;
    }

    @Override
    public void run() {
        m10.awaitA();
    }
}

class Thread10B extends Thread{
    private MyThread10 m10;

    public Thread10B(MyThread10 m10) {
        this.m10 = m10;
    }

    @Override
    public void run() {
        m10.awaitB();
    }
}